(function (root, factory) {
    if (typeof exports === 'object') {
        // CommonJS
        module.exports = exports = factory(require('./core'));
    } else {
        if (typeof define === 'function' && define.amd) {
            // AMD
            define(['./core'], factory);
        } else {
            // Global (browser)
            factory(root.CryptoJS);
        }
    }
})(this, function (CryptoJS) {
    (function () {
        // Shortcuts
        var C = CryptoJS;
        var C_lib = C.lib;
        var WordArray = C_lib.WordArray;
        var C_enc = C.enc;
        /**
         * UTF-16 BE encoding strategy.
         */

        var Utf16BE =
            (C_enc.Utf16 =
            C_enc.Utf16BE =
                {
                    /**
                     * Converts a word array to a UTF-16 BE string.
                     *
                     * @param {WordArray} wordArray The word array.
                     *
                     * @return {string} The UTF-16 BE string.
                     *
                     * @static
                     *
                     * @example
                     *
                     *     var utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
                     */
                    stringify: function (wordArray) {
                        // Shortcuts
                        var words = wordArray.words;
                        var sigBytes = wordArray.sigBytes; // Convert

                        var utf16Chars = [];

                        for (var i = 0; i < sigBytes; i += 2) {
                            var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 65535;
                            utf16Chars.push(String.fromCharCode(codePoint));
                        }

                        return utf16Chars.join('');
                    },

                    /**
                     * Converts a UTF-16 BE string to a word array.
                     *
                     * @param {string} utf16Str The UTF-16 BE string.
                     *
                     * @return {WordArray} The word array.
                     *
                     * @static
                     *
                     * @example
                     *
                     *     var wordArray = CryptoJS.enc.Utf16.parse(utf16String);
                     */
                    parse: function (utf16Str) {
                        // Shortcut
                        var utf16StrLength = utf16Str.length; // Convert

                        var words = [];

                        for (var i = 0; i < utf16StrLength; i++) {
                            words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
                        }

                        return WordArray.create(words, utf16StrLength * 2);
                    }
                });
        /**
         * UTF-16 LE encoding strategy.
         */

        C_enc.Utf16LE = {
            /**
             * Converts a word array to a UTF-16 LE string.
             *
             * @param {WordArray} wordArray The word array.
             *
             * @return {string} The UTF-16 LE string.
             *
             * @static
             *
             * @example
             *
             *     var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
             */
            stringify: function (wordArray) {
                // Shortcuts
                var words = wordArray.words;
                var sigBytes = wordArray.sigBytes; // Convert

                var utf16Chars = [];

                for (var i = 0; i < sigBytes; i += 2) {
                    var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 65535);
                    utf16Chars.push(String.fromCharCode(codePoint));
                }

                return utf16Chars.join('');
            },

            /**
             * Converts a UTF-16 LE string to a word array.
             *
             * @param {string} utf16Str The UTF-16 LE string.
             *
             * @return {WordArray} The word array.
             *
             * @static
             *
             * @example
             *
             *     var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
             */
            parse: function (utf16Str) {
                // Shortcut
                var utf16StrLength = utf16Str.length; // Convert

                var words = [];

                for (var i = 0; i < utf16StrLength; i++) {
                    words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
                }

                return WordArray.create(words, utf16StrLength * 2);
            }
        };

        function swapEndian(word) {
            return ((word << 8) & 4278255360) | ((word >>> 8) & 16711935);
        }
    })();

    return CryptoJS.enc.Utf16;
});
